package com.tianyiyan.dao.tyenword;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.tianyiyan.email.TyMail;
import com.tianyiyan.hibernate.user.EmailVerification;
import com.tianyiyan.hibernate.user.User;
import com.tianyiyan.utils.HibernateUtils;
import com.tianyiyan.utils.MessageDigestUtils;

public class UserDao
{
	public enum ResultType{
		SUCCESS,
		ERROR,
		USER_NAME_EXIST,
		EMAIL_EXIST,
		OVERDUE
	}
	/**
	 * save User for signup
	 * @param user
	 * @return has success
	 */
	public ResultType save(User user)
	{
		Session session = HibernateUtils.getInstance().getSession();
		Transaction transaction = session.beginTransaction();
		
		Query queryCheckEmail = session.createQuery("FROM User WHERE email=:email");
		if (!queryCheckEmail.setString("email", user.getEmail()).list().isEmpty())
		{
			transaction.commit();
			return ResultType.EMAIL_EXIST;
		}
		Query queryCheckName = session.createQuery("FROM User WHERE name=:name");
		if (!queryCheckName.setString("name", user.getName()).list().isEmpty())
		{
			transaction.commit();
			return ResultType.USER_NAME_EXIST;
		}
		user.setPasswd(MessageDigestUtils.encodeByMD5(user.getPasswd()));
		
		session.save(user);
		
        EmailVerification verification = new EmailVerification();
		verification.setUser(user);
		// Create Token
		Date date = new Date();
		String token = user.getEmail() + date;
		String tokenMD5 = MessageDigestUtils.encodeByMD5(token);
		verification.setCode(tokenMD5);
		// Calculate Deadline
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.HOUR_OF_DAY,2);
		verification.setDeadline(calendar.getTime());
		session.save(verification);
		// Send Email
		TyMail.send(user.getEmail(), user.getName(), tokenMD5);
		
		transaction.commit();
		return ResultType.SUCCESS;
	}
	/**
	 * check User for login
	 * @param user
	 * @return has success
	 */
	public User checkUser(User user)
	{
		Session session = HibernateUtils.getInstance().getSession();
		Transaction transaction = session.beginTransaction();
		
		Query query = session.createQuery("FROM User WHERE email=:email AND passwd=:passwd");
		List<User> users = query.setString("email", user.getEmail())
				.setString("passwd", MessageDigestUtils.encodeByMD5(user.getPasswd()))
				.list();
		if (users.size() > 0)
		{
			transaction.commit();
			return users.get(0);
		}
		
		transaction.commit();
		return null;
	}
	public void deleteOverdueUsers(Integer interval)
	{
		Session session = HibernateUtils.getInstance().getSession();
		Transaction transaction = session.beginTransaction();
		
		Query query = session.createQuery("FROM User WHERE hasVerification=FALSE AND timestamp(createDate + :second) < now()");
		List<User> users = query.setInteger("second", interval).list();
		
		for (User user : users)
		{
			Query queryEv = session.createQuery("From EmailVerification WHERE user=:user");
			List<EmailVerification> evs = queryEv.setEntity("user", user).list();
			for (EmailVerification ev : evs)
				session.delete(ev);
			session.delete(user);
		}
		transaction.commit();
	}
	/**
	 * resend EmailVerification
	 * @param user
	 * @note 
	 * 		1. send before.please make sure user hasn't passed EmailVerification
	 * 			function will not check user whether passed EmailVerification
	 * 		2. send before.please make sure user exist.
	 * 			function will not check user whether exist
	 * @return whether success
	 */
	public boolean resendEmailVerification(User user)
	{
		Session session = HibernateUtils.getInstance().getSession();
		Transaction transaction = session.beginTransaction();
		/// Step.1 delete old EmailVerification
		Query queryEv = session.createQuery("From EmailVerification WHERE user=:user");
		List<EmailVerification> evs = queryEv.setEntity("user", user).list();
		for (EmailVerification ev : evs)
			session.delete(ev);
		
		/// Step.2 create new EmailVerification and save it
		EmailVerification verification = new EmailVerification();
		verification.setUser(user);
		///	 (1) Create Token
		Date date = new Date();
		String token = user.getEmail() + date;
		String tokenMD5 = MessageDigestUtils.encodeByMD5(token);
		verification.setCode(tokenMD5);
		///	 (2) Calculate Deadline
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.HOUR_OF_DAY,2);
		verification.setDeadline(calendar.getTime());
		session.save(verification);
		
		/// Step.3 send email
		TyMail.send(user.getEmail(), user.getName(), tokenMD5);
		transaction.commit();
		return true;
	}
	public ResultType emailVerification(String token)
	{
		Session session = HibernateUtils.getInstance().getSession();
		Transaction transaction = session.beginTransaction();
		
		Query query = session.createQuery("From EmailVerification WHERE code=:token");
		List<EmailVerification> evs = query.setString("token", token).list();
		if (evs.size() < 1)
			return ResultType.ERROR;
		EmailVerification ev = evs.get(0);
		
		if (ev.getDeadline().before(new Date()))
			return ResultType.OVERDUE;
		
		User user = ev.getUser();
		user.setHasVerification(true);
		
		session.delete(ev);
		
		transaction.commit();
		return ResultType.SUCCESS;
	}
	
	public User getUser(Integer id)
	{
		Session session = HibernateUtils.getInstance().getSession();
		Transaction transaction = session.beginTransaction();
		
		User user = (User)session.get(User.class, id);
		
		transaction.commit();
		return user;
	}
}
